﻿using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Threading.Tasks;

namespace Red.Launcher.ActiveDirectory
{
    public class Fetcher<PrincipalType> where PrincipalType : Principal
    {
        #region Public Methods

        public void Fetch()
        {
            PrincipalContext ctx = new PrincipalContext( ContextType.Domain );
            PrincipalType searchType = (PrincipalType)Activator.CreateInstance( typeof( PrincipalType ), new object[] { ctx } );
            PrincipalSearcher search = new PrincipalSearcher( searchType );

            foreach ( Principal found in search.FindAll() )
            {
                PrincipalType principal = found as PrincipalType;

                if( principal != null )
                {
                    Principal?.Invoke( principal );
                }
            }
        }

        #endregion Public Methods

        #region Events

        public delegate void PrincipalHandler( PrincipalType principal );
        public event PrincipalHandler Principal;

        #endregion Events
    }

    public class AsyncFetcher<PrincipalType> where PrincipalType : Principal
    {
        #region Public Properties

        public ICollection<PrincipalType> Items { get; private set; } = new List<PrincipalType>();

        #endregion Public Properties

        #region Public Methods

        public async Task Fetch()
        {
            Items.Clear();

            Fetcher<PrincipalType> fetcher = new Fetcher<PrincipalType>();

            fetcher.Principal += Fetcher_Principal;

            await Task.Run( () => { fetcher.Fetch(); } );
        }

        #endregion Public Methods

        #region Event Handlers

        private void Fetcher_Principal( PrincipalType principal )
        {
            Items.Add( principal );
        }

        #endregion Event Handlers
    }
}
